package org.fin.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.fin.io.Resources;
import org.fin.pojo.Configuration;
import org.fin.pojo.MappedStatement;

import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * 解析框架XML配置文件
 */
public class ConfigurationBuilder {


  private Configuration configuration;

  public ConfigurationBuilder() {
    configuration = new Configuration();
  }


  public Configuration parseConfig(InputStream in) throws DocumentException, PropertyVetoException {
    Document doc = new SAXReader().read(in);
    
    // <configuration>
    Element root = doc.getRootElement();
    configureDataSource(root);
    configureMapperStatements(root);

    return configuration;
  }



  /**
   * 根据给定的xml配置文件根标签，查询mapper相关的配置信息，并且将对应的的sql配置信息配置在{@link #configuration}对象中
   *
   * @param root  核心配置文件的根标签：<configuration>
   */
  @SuppressWarnings("unchecked")
  private void configureMapperStatements(Element root) throws DocumentException {
    List<Element> mapperList = root.selectNodes("//mapper");

    for (Element element : mapperList) {
      String path = element.attributeValue("resource");
      InputStream mapperIn = Resources.getResourceAsStream(path);
      Map<String, MappedStatement> statementsMap = new MapperStatementBuilder().parse(mapperIn);
      configuration.putMappedStatements(statementsMap);
    }
  }



  /**
   * 根据给定的xml配置文件根标签，查找datasource的配置信息并配置在{@link #configuration}对象中
   *
   * @param root  核心配置文件的根标签：<configuration>
   */
  @SuppressWarnings("unchecked")
  private void configureDataSource(Element root) throws PropertyVetoException {
    List<Element> list = root.selectNodes("//property");

    Properties properties = new Properties();
    for (Element element : list) {
      String name = element.attributeValue("name");
      String value = element.attributeValue("value");
      properties.setProperty(name, value);
    }

    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setDriverClass(properties.getProperty("driverClass"));
    dataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
    dataSource.setUser(properties.getProperty("username"));
    dataSource.setPassword(properties.getProperty("password"));

    configuration.setDataSource(dataSource);
  }
}
